package com.googlecode.yoohoo.xmppcore;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.osgi.framework.BundleContext;
import org.osgi.framework.ServiceReference;
import org.osgi.util.tracker.ServiceTracker;
import org.osgi.util.tracker.ServiceTrackerCustomizer;

import com.googlecode.yoohoo.osgi.IBundleContextAware;
import com.googlecode.yoohoo.server.IServer;
import com.googlecode.yoohoo.xmppcore.connection.DefaultConnectionHandler;
import com.googlecode.yoohoo.xmppcore.connection.IConnectionHandler;
import com.googlecode.yoohoo.xmppcore.io.IConnector;
import com.googlecode.yoohoo.xmppcore.parsing.ParsersTracker;
import com.googlecode.yoohoo.xmppcore.protocol.parsing.IXmppParsingFactory;
import com.googlecode.yoohoo.xmppcore.protocol.parsing.PredefinedXmppParsingFactory;

public class Server implements IServer, IBundleContextAware {
	private static final Log log = LogFactory.getLog(Server.class);
	private BundleContext bundleContext;
	private ServiceTracker connectorTracker;
	private IConnectionHandler connectionHandler;
	private ParsersTracker parsersTracker;
	private IXmppParsingFactory parsingFactory;
	
	@Override
	public void start() throws Exception {
		parsingFactory = new PredefinedXmppParsingFactory();
		bundleContext.registerService(IXmppParsingFactory.class.getName(), parsingFactory, null);
		
		parsersTracker = new ParsersTracker(bundleContext, parsingFactory, "stanza");
		parsersTracker.open();
		
		connectionHandler = new DefaultConnectionHandler(bundleContext);
		
		connectorTracker = new ServiceTracker(bundleContext, IConnector.class.getName(),
				new ConnectorTrackerCustomizer());
		connectorTracker.open();
		
		// TODO Auto-generated method stub
		log.info("YooHoo IM server started.");
	}

	@Override
	public void stop() throws Exception {
		connectorTracker.close();
		
		parsersTracker.close();
		// TODO Auto-generated method stub
		log.info("YooHoo IM server stopped.");
	}

	@Override
	public void setBundleContext(BundleContext bundleContext) {
		this.bundleContext = bundleContext;
	}
	
	private class ConnectorTrackerCustomizer implements
				ServiceTrackerCustomizer {
		@Override
		public Object addingService(ServiceReference reference) {
			IConnector connector = (IConnector)Server.this.bundleContext.getService(reference);
			if (connector != null) {
				try {
					connector.initialize(Server.this.connectionHandler);
				} catch (Exception e) {
					if (log.isErrorEnabled()) {
						log.error(String.format("An error occured while initializing connector '%s'.",
								connector.getClass().getName()));
					}
					e.printStackTrace();					
					return null;
				}
			}
			
			return connector;
		}

		@Override
		public void modifiedService(ServiceReference reference, Object service) {
			// do nothing
		}

		@Override
		public void removedService(ServiceReference reference, Object service) {
			if (service != null) {
				IConnector connector = (IConnector)service;
				try {
					connector.destroy();
				} catch (Exception e) {
					if (log.isErrorEnabled()) {
						log.error(String.format("An error occured while destroying connector '%s'.",
								connector.getClass().getName()));
					}
					e.printStackTrace();
				}
			}
		}
	}
	
}
